package prog2012.practico1.listas;

/**
 * Clase de pruebas para evaluar los m�todos b�sicos de la implementaci�n de TLista.
 * 
 * @author C�tedra de Programacion 2
 * @version 1.0
 */

import java.util.Random;

import junit.framework.TestCase;

@SuppressWarnings("rawtypes")
public class TestTListaBasico extends TestCase {
	private static final int MAX_ELEM = 3000; // Cantidad de Elementos utilizados para cargar la lista.-
	private static final String TEXTO = "Bienvenidos al texto de prueba de Programacion Dos Si has pasado este caso quiere decir que vas por buen camino";
	
	protected ILista miLista;
	
	public void setUp(){
		miLista = new TLista();
	}
	
	private Comparable[] copiarLista() {
		Comparable[] datos = new Comparable[miLista.obtenerCantidadElementos()];
		IElemento aux = miLista.obtenerPrimero();
		int i = 0;
		while (aux != null) {
			datos[i] = aux.getEtiqueta();
			aux = aux.getSiguiente();
			i++;
		}
		return datos;
	}
	
	private void validarInsercionesInvalidas() {
		assertNotNull("La lista deber�a esta creada",miLista);
		assertTrue("La lista deber�a estar vac�a", miLista.esVacia());
		assertFalse("Los elementos a insertar no pueden ser inv�lidos",miLista.insertarAlPrincipio(null));
		assertFalse("Los elementos a insertar no pueden ser inv�lidos",miLista.insertarAlFinal(null));
		assertTrue("La lista deber�a seguir estando vac�a",miLista.esVacia());
	}
	
	@SuppressWarnings("unchecked")
	protected void verificarListaOrdenada() {
		IElemento aux = miLista.obtenerPrimero();
		while (aux != null) {
			IElemento auxSig = aux.getSiguiente();
			if (auxSig != null) {
				assertTrue("El elemento actual deber�a ser menor que su siguiente", aux.getEtiqueta().compareTo(auxSig.getEtiqueta()) < 0);
			}
			aux = aux.getSiguiente();
		}
	}
	
	protected Comparable[] cargarDatosEnLista() {
		validarInsercionesInvalidas();
		
		for (int i = 0; i < MAX_ELEM; i++) {
			Random rnd = new Random();
			TElemento elem = new TElemento(rnd.nextInt(Integer.MAX_VALUE) , null);
			if (i % 2 == 0) {
				assertTrue("Deber�a poder insertar el elemento", miLista.insertarAlFinal(elem));
			} else {
				assertTrue("Deber�a poder insertar el elemento", miLista.insertarAlPrincipio(elem));
			}
		}
		
		assertNotNull("Deber�a existir el primer elemento.", miLista.obtenerPrimero());
		Comparable[] datos = copiarLista();
		assertFalse("Deber�a haber elementos en la lista", datos.length <= 0);
		return datos;
	}
	
	protected String cargarDatosEnString() {
		Comparable[] datos = cargarDatosEnLista();
		StringBuilder resCorr = new StringBuilder();
		for (int i = 0; i < datos.length; i++) {
			if (resCorr.length() > 0){
				resCorr.append(TLista.SEPARADOR_ELEMENTOS_IMPRESOS);
			}
			resCorr.append(datos[i]);
		}
		return resCorr.toString();
	}
	
	public void testEsVacia() {
		cargarDatosEnLista();
		assertFalse("Si cargo informaci�n en la lista, la misma deber�a dejar de estar vac�a", miLista.esVacia());
	}
	
	public void testObtenerPrimero() {
		assertNull("Si la lista est� vac�a, no deber�a tener un elemento primero", miLista.obtenerPrimero());
		Comparable[] datos = cargarDatosEnLista();
		IElemento elemPri = miLista.obtenerPrimero();
		assertNotNull("Si le cargo informaci�n a la lista, deber�a tener un primer elemento", elemPri);
		assertEquals("La etiqueta del primer elemento deber�a ser el primer elemento cargado", elemPri.getEtiqueta(), datos[0]);
	}

	public void testObtenerUltimo() {
		assertNull("Si la lista est� vac�a, no deber�a tener un elemento ultimo", miLista.obtenerUltimo());
		Comparable[] datos = cargarDatosEnLista();
		IElemento elemUlt = miLista.obtenerUltimo();
		assertNotNull("Si le cargo informaci�n a la lista, deber�a tener un �ltimo elemento", elemUlt);
		assertEquals("La etiqueta del ultimo elemento deber�a ser el ultimo elemento cargado", elemUlt.getEtiqueta(), datos[datos.length-1]);
	}
	
	public void testBuscarEnLista() {
		assertNull("No deber�a poder buscar un elemento nulo", miLista.buscar(null));
		Comparable[] datos = cargarDatosEnLista();
		
		for (int i = 0; i < datos.length; i++) {
			assertNotNull("Deber�a poder encontrar este elemento, ya que fue ingresado en la lista", miLista.buscar(datos[i]));
		}
		
		assertNull("No deber�a poder encontrar un elemento inexistente", miLista.buscar(-1));
	}
	
	public void testBuscarEliminar() {
		Comparable[] datos = cargarDatosEnLista();

		for (int i = 0; i < datos.length; i++) {
			IElemento unElemento = miLista.buscar(datos[i]);
			assertNotNull("Deber�a poder encontrar este elemento, ya que fue ingresado en la lista", unElemento);
			assertEquals("Deber�a poder eliminar el elemento", unElemento, miLista.eliminar(datos[i]));
			assertNull("Luego de haberlo eliminado, no deber�a existir mas",miLista.buscar(datos[i]));
		}
		assertNull("No deber�a poder eliminar un elemento inexistente", miLista.eliminar(-1111));
		assertNull("No deber�a poder eliminar un elemento nulo", miLista.eliminar(null));
	}

	public void testObtenerCantidadElementos() {
		assertEquals("Cuando la lista est� vac�a, deber�a tener 0 elementos", miLista.obtenerCantidadElementos(), 0);
		Comparable[] datos = cargarDatosEnLista();
		assertEquals("Luego de cargar elementos, deber�a actualizarse la cantidad", miLista.obtenerCantidadElementos(), datos.length);
		assertNotNull("Deber�a poder eliminar este elemento", miLista.eliminar(datos[MAX_ELEM / 2]));
		assertEquals("Luego de haber eliminado un elemento, la cantidad deber�a actualizarse", miLista.obtenerCantidadElementos(), datos.length-1);
	}

	
	public void testVaciar() {
		cargarDatosEnLista();
		miLista.vaciar();
		assertTrue("Luego de vaciar la lista, deber�a quedar vac�a", miLista.esVacia());
		assertEquals("La cantidad de elementos, luego de vaciar una lista, deber�a ser 0", miLista.obtenerCantidadElementos(), 0);
		assertNull("No deber�a tener un elemento primero", miLista.obtenerPrimero());
		assertNull("No deber�a tener un elemento �ltimo", miLista.obtenerUltimo());
	}

	public void testInsertarOrdenado() {
		Comparable[] datos = cargarDatosEnLista();
		miLista.vaciar();
		
		for (int i = 0; i < datos.length; i++) {
			TElemento elem = new TElemento(datos[i], null);
			assertTrue("Deber�a poder ingresar el elemento a la lista", miLista.insertarOrdenado(elem));
		}

		IElemento primero = miLista.obtenerPrimero();
		IElemento ultimo = miLista.obtenerUltimo();
		assertNotNull("Deber�a tener un primer elemento", primero);
		assertNotNull("Deber�a tener un ultimo elemento", ultimo);
		assertEquals("La cantidad de elementos deber�a quedar intacta", datos.length, miLista.obtenerCantidadElementos());

		verificarListaOrdenada();
	}

	public void testToArray() {
		Comparable[] res = miLista.etiquetasToArray();
		assertNotNull("El vector no deber�a ser vac�o si la lista esta vac�a", res);
		assertEquals("El vector no deber�a contener elementos si la lista est� vac�a", res.length, 0);
		
		Comparable[] datos = cargarDatosEnLista();
		res = miLista.etiquetasToArray();
		assertEquals ("Deber�an tener la misma cantidad de elementos", res.length, datos.length);
		for (int j = 0; j < res.length; j++) {
			assertEquals("Deber�a tener los mismos elementos", res[j], datos[j]);
		}
	}
	
	public void testCargarOtrosTipos() {
		validarInsercionesInvalidas();
		String[] palabras = TEXTO.split(" ");
		for (int i = 0; i < palabras.length; i++) {
			TElemento elem = new TElemento(palabras[i] , null);
			assertTrue("Deber�a poder insertar este elemento", miLista.insertarAlFinal(elem));
		}
		
		Comparable[] datos = copiarLista();
		assertFalse("Deber�a tener elementos", datos.length <= 0);
	}

}
